﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Tetris
{
    [XmlInclude(typeof(LeftL))]
    [XmlInclude(typeof(LeftS))]
    [XmlInclude(typeof(RightS))]
    [XmlInclude(typeof(RightL))]
    [XmlInclude(typeof(Arrow))]
    [XmlInclude(typeof(Line))]
    [XmlInclude(typeof(Square))]
    [Serializable]
    public class Shape
    {
        public const int CLOCKWISE=1;
        public const int COUNTCLOCKWISE= -1;
        public static int Nbstate = 0;
        protected List<Point> points = new List<Point>();
        protected int state;
        protected String image;
       
        /// <summary>
        /// basic constructor
        /// </summary>
        public Shape()
        {
            for (int i = 0; i < 4; i++)
            {
                points.Add(new Point(0,0));
            }
            image = "../../../images/yellow.png";
        }

        /// <summary>
        /// Get/Set the list of Points for this shape
        /// </summary>
        public List<Point> Points
        {
            get
            {
                return points;
            }
            set
            {
                points = value;
            }
        }

        /// <summary>
        /// get/set state
        /// </summary>
        public int State
        {
            get
            {
                return state;
            }
            set
            {
                state = value;
            }
        }

        public String Image
        {
            get
            {
                return image;
            }
            set
            {
                image = value;
            }
        }

        /// <summary>
        /// Move left
        /// </summary>
        /// <param name="game">Current Game</param>
        public void moveLeft(Game game)
        {
            foreach(Point p in points)
            {
                p.X=p.X - 1;
            }
        }

        /// <summary>
        /// Move Right
        /// </summary>
        /// <param name="game">Current Game</param>
        public void moveRight(Game game)
        {
            foreach (Point p in points)
            {
                p.X=p.X + 1;
            }
        }
        
        /// <summary>
        /// Move Down
        /// </summary>
        /// <param name="game">Current Game</param>
        public void moveDown(Game game)
        {
            foreach (Point p in points)
            {
                p.Y=p.Y+ 1;
            }
        }

        /// <summary>
        /// Put the shape on the plateau
        /// </summary>
        /// <param name="game"></param>
        public void setOnPlateau(Game game)
        {
            foreach (Point p in points)
            {
                game.Plateau[p.X][p.Y].Available=false;
            }
        }

        /// <summary>
        /// Check that the shape can make its next movement
        /// </summary>
        /// <param name="move"> Direction</param>
        /// <param name="game">Current Game</param>
        /// <returns></returns>
        public bool canMove(String move, Game game)
        {
            switch (move)
            {
                case "down":
                    foreach (Point p in points)
                    {
                        if (!game.Plateau[p.X][p.Y+1].Available)
                        {
                            return false;
                        }
                    }
                    break;
                case "right":
                    foreach (Point p in points)
                    {
                        if (!game.Plateau[p.X+1][p.Y].Available)
                        {              
                            return false;
                        }
                    }
                    break;
                case "left":
                    foreach (Point p in points)
                    {
                        if (!game.Plateau[p.X-1][p.Y].Available)
                        {
                            return false;
                        }
                    }
                    break;
            }
            return true;
        }

        /// <summary>
        /// Check that the shape can rotate
        /// </summary>
        /// <param name="game">Current Game</param>
        /// <param name="sens">Rotation direction</param>
        /// <returns></returns>
        public bool canRotate(Game game, int sens)
        {
            this.rotate(sens);
            foreach (Point p in points)
            {
                if (!game.Plateau[p.X][p.Y].Available)
                {
                    this.rotate(-1*sens);
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Check that the shape can be here, used when players tries to rotate a shape near a border of the game
        /// </summary>
        /// <param name="game">Current Game</param>
        /// <returns></returns>
        public bool canBeHere(Game game)
        {
            foreach (Point p in points)
            {
                if (!game.Plateau[p.X][p.Y].Available)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Virtual function of rotate that will be implements in Child classes of Shape
        /// </summary>
        /// <param name="sens"></param>
        public virtual void rotate(int sens = 1)
        {
        }

    }
}
